# Copyright (C) 2025 All rights reserved.
#   
# @File oauth2_logins.py
# @Brief 
# @Author 杨嘉祥, vnimy@mediad.cn
# @Version 1.0
# @Date 2025-01-26
#
import frappe
from frappe_wxwork.utils import url_util
from urllib.parse import quote, urlparse
from frappe import _
import frappe.utils
from frappe.utils.oauth import get_oauth_keys, login_oauth_user

from .wxworkapi.CorpApi import *

def authorize_url(corp_id, redirect_uri, state=None):
    """
    构造网页授权链接
    详情请参考
    https://work.weixin.qq.com/api/doc#90000/90135/91022

    :param redirect_uri: 授权后重定向的回调链接地址
    :param state: 重定向后会带上 state 参数
    :return: 返回的 JSON 数据包
    """
    # redirect_uri = six.moves.urllib.parse.quote(redirect_uri, safe=b'')
    redirect_uri = quote(redirect_uri, safe=b'')
    url_list = [
        'https://open.weixin.qq.com/connect/oauth2/authorize',
        '?appid=',
        corp_id,
        '&redirect_uri=',
        redirect_uri,
        '&response_type=code&scope=snsapi_base',
    ]
    if state:
        url_list.extend(['&state=', state])
    url_list.append('#wechat_redirect')
    return ''.join(url_list)

# http://127.0.0.1:8000/api/method/frappe_wxwork.oauth2_logins.redirect?url=/app/home
@frappe.whitelist(allow_guest=True)
def redirect(url):
    netloc = urlparse(url).netloc
    if netloc is None or "" == netloc:
        url = url_util.append_domain_protocol(url)

    is_logged_in = frappe.session.user != "Guest"
    if is_logged_in:
        # 已经登录了，直接重定向
        frappe.local.response["type"] = "redirect"
        frappe.local.response["location"] = url

    else:
        # 企业微信oauth2
        # 获取社交登录密钥
        settings = frappe.get_single("WXWork Settings")
        provider = settings.social_login_key
        if not provider:
            return frappe.respond_as_web_page(
                "登录失败",
                "未配置企业微信登录",
                success=False,
            )
        params = get_oauth_keys(provider)

        corpid = params.get("client_id")
        corpsecret = params.get("client_secret")

        wx_login_url = url_util.append_domain_protocol("/api/method/frappe_wxwork.oauth2_logins.wxwork_login")
        redirect_url = authorize_url(corpid,wx_login_url, quote(url))

        frappe.local.response["type"] = "redirect"
        frappe.local.response["location"] = redirect_url

# http://127.0.0.1:8000/api/method/frappe_wxwork.oauth2_logins.wxwork_login
@frappe.whitelist(allow_guest=True)
def wxwork_login(code, state):
	# 获取社交登录密钥
    settings = frappe.get_single("WXWork Settings")
    provider = settings.social_login_key
    if not provider:
        return frappe.respond_as_web_page(
            "登录失败",
            "未配置企业微信登录",
            success=False,
        )
    params = get_oauth_keys(provider)
    corpid = params.get("client_id")
    corpsecret = params.get("client_secret")

    # 获取访问用户身份
    api = CorpApi(corpid, corpsecret)
    info = api.httpCall(CORP_API_TYPE['GET_USER_INFO_BY_CODE'], { "code" : code })

    def to_redirect():
        frappe.local.response["type"] = "redirect"
        frappe.local.response["location"] = state

    if 0 != info['errcode']:
        return to_redirect()

    wxid = info['userid']
    en_user = frappe.get_value("WXWork User", {"corpid": corpid, "userid": wxid}, "user")
    if en_user is None:
        return to_redirect()

    frappe.local.login_manager.user = en_user
    frappe.local.login_manager.post_login()
    to_redirect()

@frappe.whitelist(allow_guest=True)
def login_via_wxwork(code: str, state: str):
	# 获取社交登录密钥
	settings = frappe.get_single("WXWork Settings")
	provider = settings.social_login_key
	if not provider:
		return frappe.respond_as_web_page(
			"登录失败",
			"未配置企业微信登录",
			success=False,
		)
	params = get_oauth_keys(provider)
	corpid = params.get("client_id")
	corpsecret = params.get("client_secret")

	# 获取访问用户身份
	api = CorpApi(corpid, corpsecret)
	response = api.httpCall(CORP_API_TYPE['GET_USER_INFO_BY_CODE'], { "code" : code })

	errCode = response.get('errcode')
	errMsg = response.get('errmsg')
	if errCode > 0:
		return frappe.respond_as_web_page(
				"登录失败",
				f"企业微信接口调用失败，错误码：{errCode}，错误信息：{errMsg}",
				success=False,
				http_status_code=403,
			)
	
	userid = response.get("userid")
	openid = None

	# 如果是通过微信登录，那么将openid转换成userid
	if not userid:
		openid = response.get("openid", None)
		response = api.httpCall(CORP_API_TYPE['OPENID_TO_USERID'], { "openid" : openid })
		userid = response.get("userid", None)

		if not openid:
			return frappe.respond_as_web_page(
				"登录失败",
				"无法获取用户信息",
				success=False,
				http_status_code=403,
			)

	# 获取关联的系统用户
	if userid:
		ww_user = frappe.db.exists("WXWork User", { "corpid": corpid, "userid": userid })
	else:
		ww_user = frappe.db.exists("WXWork User", { "corpid": corpid, "openid": openid })

	user = None
	if ww_user:
		user = frappe.db.get_value("WXWork User", ww_user, ["user","active","realname"])
		if not user[0] or not user[1]:
			if not user[2]:
				return frappe.respond_as_web_page(
							"登录失败",
							f"请您填写下面信息，以方便系统管理员为您开通！<form action='/api/method/frappe_wxwork.oauth2_logins.save' method='post'><input type='hidden' name='id' value='{ww_user}'><br/>您的姓名:<input type='text' name='realname' value=''><br/>手机号码:<input type='text' name='phone' value=''><br/><input type='submit' value='提交'></form>"
							)
			else:
				return frappe.respond_as_web_page(
					"登录失败",
					f"用户:{user[2]}，您的系统账号尚未开通！请联系系统管理员。",
					success=False,
					http_status_code=403,
				)
		else:
			# oauth登录
			info = { "email": user[0], "userid": userid, "sub": userid }
			login_oauth_user(info, provider=provider, state=state)
	elif settings.auto_insert_unbind_user:
		# 插入新访问用户
		wwu_doc = frappe.new_doc("WXWork User")
		wwu_doc.update({ "corpid": corpid, "userid": userid, "openid": openid })
		wwu_doc.insert(ignore_permissions=True, ignore_if_duplicate=True)
		frappe.db.commit()
		if userid:
			ww_user = frappe.db.exists("WXWork User", { "corpid": corpid, "userid": userid })
		else:
			ww_user = frappe.db.exists("WXWork User", { "corpid": corpid, "openid": openid })
		return frappe.respond_as_web_page(
					"",
					f"您还不是系统用户，请您填写下面信息，以方便系统管理员为您开通！<form action='/api/method/frappe_wxwork.oauth2_logins.save' method='post'><input type='hidden' name='id' value='{ww_user}'><br/>您的姓名:<input type='text' name='realname' value=''><br/>手机号码:<input type='text' name='phone' value=''><br/><input type='submit' value='提交'></form>"
					)
	else:
		return frappe.respond_as_web_page(
			"登录失败",
			f"无法获取用户信息！",
			success=False,
			http_status_code=403,
		)

# http://127.0.0.1:8000/api/method/frappe_wxwork.oauth2_logins.save
@frappe.whitelist(allow_guest=True)
def save():
	request = frappe.request.__dict__
	print(request.get("form")) 
	if request.get("form").get("id"):
		wwu_doc = frappe.get_doc("WXWork User", request.get("form").get("id"))
		wwu_doc.update({ "realname": request.get("form").get("realname"), "phone": request.get("form").get("phone")})
		wwu_doc.save(ignore_permissions=True)
		return frappe.respond_as_web_page(
			"保存成功",
			f"保存成功！请联系管理员开通!",
			success=True,
			# http_status_code=200,
		)
	else:
		return frappe.respond_as_web_page(
			"保存失败",
			f"无法获取用户信息！",
			success=False,
			http_status_code=403,
		)

# http://127.0.0.1:8000/api/method/frappe_wxwork.oauth2_logins.ua
@frappe.whitelist(allow_guest=True)
def ua():
	request_dict = frappe.request.__dict__
	user_agent = request_dict.get("environ", {}).get("HTTP_USER_AGENT")
	return user_agent